package com.cash.app.net

import com.cash.app.constant.AppConstant.APP_CHANNEL
import com.cash.app.constant.AppConstant.IMAGE_BASE_64
import com.cash.app.constant.AppConstant.K_AJ_ID
import com.cash.app.constant.AppConstant.K_CHANNEL
import com.cash.app.constant.AppConstant.K_WX_CODE
import com.cash.app.manager.LoginManager
import com.cash.app.net.NetConstant.BV_APP_VERSION
import com.cash.app.net.NetConstant.BV_CLIENT_TYPE
import com.cash.app.net.NetConstant.BV_ZONE_EN
import com.cash.app.net.NetConstant.B_APP_VERSION
import com.cash.app.net.NetConstant.B_CLIENT_TYPE
import com.cash.app.net.NetConstant.B_DATA
import com.cash.app.net.NetConstant.B_ZONE
import com.cash.app.net.NetConstant.METHOD_POST
import com.cash.app.utils.SpUtils
import com.cash.app.utils.TLog
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONObject

class BaseBodyInterceptor : Interceptor {

    private val TAG = "BaseBodyInterceptor"

    // add base body
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()

        if (originalRequest.method == METHOD_POST) {
            val originBody = originalRequest.body

            val newBody = addCommonBody(originBody)
            //TLog.d("newBody=${newBody}", TAG)

            val contentType = originBody?.contentType() ?: NetConstant.HV_CONTENT_TYPE.toMediaType()
            TLog.d("contentType=${contentType}", TAG)

            val newRequest =
                originalRequest.newBuilder().post(newBody.toString().toRequestBody(contentType))
                    .build()

            return chain.proceed(newRequest)
        } else {
            TLog.d("intercept other method=${originalRequest.method}", TAG)
            return chain.proceed(originalRequest)
        }
    }

    private fun addCommonBody(originBody: RequestBody?): JSONObject {
        val hasBody = originBody != null
        TLog.d("addCommonBody hasBody=$hasBody", TAG)
        return JSONObject().apply {
            put(B_ZONE, BV_ZONE_EN)
            put(B_APP_VERSION, BV_APP_VERSION)
            put(B_CLIENT_TYPE, BV_CLIENT_TYPE)

            SpUtils.get(K_CHANNEL, APP_CHANNEL).takeIf { it.isNotEmpty() }?.let {
                put(K_CHANNEL, it)
            }

            SpUtils.get(K_AJ_ID, "").takeIf { it.isNotEmpty() }?.let {
                put(K_AJ_ID, it)
            }
            var token = LoginManager.getToken()
            if (token.isEmpty()) {
                token = SpUtils.get(K_WX_CODE, "")
            }
            TLog.d("addCommonBody finalToken=$token", TAG)
            put(K_WX_CODE, token)

            TLog.d("addCommonBody baseBody=${this}", TAG)
            if (hasBody) {
                val customBodyStr = originBody!!.asString()
                if (customBodyStr.isNotEmpty()) {
                    // data is not null
                    val dataObject = JSONObject(customBodyStr)
                    if (!customBodyStr.contains(IMAGE_BASE_64)) {
                        TLog.d("addCommonBody customBody=${dataObject}", TAG)
                    }
                    put(B_DATA, dataObject)
                } else {
                    // data is null, add empty object
                    TLog.d("addCommonBody customBody is null", TAG)
                    put(B_DATA, JSONObject())
                }
            } else {
                TLog.e("addCommonBody originBody is null", TAG)
            }
        }
    }

    private fun RequestBody.asString(): String {
        val buffer = Buffer()
        writeTo(buffer)
        return buffer.readUtf8()
    }
}